#ifndef MY_UTILITY_H
#define MY_UTILITY_H
#define _GNU_SOURCE
#include <sched.h>
#include <sys/types.h>
#include <fcntl.h>
#include <netinet/if_ether.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/if_tun.h>
#include <net/if.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
// #include <linux/udp.h>
#include <netinet/udp.h>
#include <netinet/ip.h>
ssize_t __write_all(int fd, const void *buf, size_t count);
ssize_t __read_all(int fd, void *buf, size_t nbytes);
int open_tap(char *tap_name);
struct arp_pck
{
    struct ether_header header;
    struct ether_arp arp;
    char fill_data[18];

} __attribute__((__packed__));
struct arp_pck arp_maker(uint8_t *sender_hardware_address, uint8_t *sender_protocol_address, uint8_t *target_hardware_address, uint8_t *target_protocol_address);
struct arp_pck arp_maker_response(uint8_t *sender_hardware_address, uint8_t *sender_protocol_address, uint8_t *target_hardware_address,
                                  uint8_t *target_protocol_address);
char *mac_get(int fd, uint8_t *target_protocl_address, uint8_t *sender_protocl_address, uint8_t *sender_hw_address);
uint16_t pck_checksum(const void *buf, const int buf_len);
int is_ip_frame(const uint8_t * frame );
uint8_t *ip_frame_src_ip(const uint8_t *frame);
uint8_t *ip_frame_dest_ip(const uint8_t *frame);
int frame_src_mac_eq_mac(const uint8_t *mac, const uint8_t *frame);
int frame_dest_mac_eq_mac(const uint8_t *mac, const uint8_t *frame);
int frame_src_ip_eq_ip(const uint8_t *ip, const uint8_t *frame);
int frame_dest_ip_eq_ip(const uint8_t *ip, const uint8_t *frame);
#define ERR(fmt, ...) printf("\033[31m[ ERRO ]\033[0m " fmt "\n", ##__VA_ARGS__);
#define LOG(fmt, ...) printf("\033[32m[ INFO ]\033[0m " fmt "\n", ##__VA_ARGS__);
#define WARN(fmt, ...) printf("\033[33m[ WARN ]\033[0m " fmt "\n", ##__VA_ARGS__);
#define safe_buf_trans_to_type(buf, type, len)                               \
    ({                                                                       \
        type *ptr = NULL;                                                    \
        do                                                                   \
        {                                                                    \
            if (sizeof(type) != len)                                         \
            {                                                                \
                WARN("buf content len not eq type len");                     \
                break;                                                       \
            }                                                                \
            ptr = malloc(sizeof(type));                                      \
            if (ptr == NULL)                                                 \
            {                                                                \
                WARN("malloc pck mem failed %s %d", strerror(errno), errno); \
                break;                                                       \
            }                                                                \
            memcpy(ptr, buf, len);                                           \
        } while (0);                                                         \
        ptr;                                                                 \
    });
#define print_arr(arr, len, format)                    \
    do                                                 \
    {                                                  \
        char format_str[10] = {0};                     \
        if (format == 'x')                             \
        {                                              \
            memcpy(format_str, "%02x ", 6);            \
        }                                              \
        else                                           \
        {                                              \
            memcpy(format_str, "%02d ", 6);            \
        }                                              \
        for (int i = 0; i < len; i++)                  \
        {                                              \
            printf(format_str, ((uint8_t *)(arr))[i]); \
            if (((i + 1) % 16) == 0)                   \
            {                                          \
                printf("\n");                          \
            }                                          \
        }                                              \
        printf("\n");                                  \
    } while (0);

#endif